package com.mstar.qs.common.io;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

import com.mstar.qs.common.DefQsException;
import com.mstar.qs.common.Entry;

public class XmlUtil {

	public static Entry parse(Document doc) throws DefQsException {

		Element root = doc.getDocumentElement();
		if (root == null)
			throw new NullPointerException("Root element is empty.");

		Entry entry;
		try {
			entry = handle(root, null);
			if (entry != null)
				entry.handleIncluding();
		} catch (Exception e) {
			throw new DefQsException(e);
		}

		return entry;
	}

	/**
	 * 
	 * @param file
	 * @return
	 * @throws SAXException
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws DefQsException
	 */
	public static Entry parseWithAbstractFile(String file) throws SAXException,
			IOException, ParserConfigurationException, DefQsException {

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		builder = factory.newDocumentBuilder();
		Document doc = builder.parse(file);
		return parse(doc);

	}

	public static Entry parse(String xmlContext, String encode)
			throws SAXException, IOException, ParserConfigurationException,
			DefQsException {
		InputStream is = null;
		if (encode != null)
			is = new ByteArrayInputStream(xmlContext.getBytes(encode));
		else
			is = new ByteArrayInputStream(xmlContext.getBytes());
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		builder = factory.newDocumentBuilder();
		Document doc = builder.parse(is);
		return parse(doc);
	}

	public static Entry parse(String xmlContext) throws SAXException,
			IOException, ParserConfigurationException, DefQsException {
		return parse(xmlContext, null);
	}

	public static Entry retrieveFromURL(String url) throws DefQsException {
		String r = "";
		try {
			r = new QsHttpClient().execute(url).getValueReturn();
			return parse(r);
		} catch (Exception e) {
			throw new DefQsException(r, e);
		}

	}

	private static Entry handle(Element le, Entry pre) throws SAXException,
			IOException, ParserConfigurationException {
		Entry entry = new Entry(le.getTagName(), pre);
		Node node = le.getFirstChild();
		if (node instanceof Text) {
			Text t = (Text) le.getFirstChild();
			String value = null;
			if (t != null) {
				value = t.getData().trim();
			}
			if (value != null)
				entry.setValue(value);
		}

		NamedNodeMap att = le.getAttributes();
		if (att.getLength() > 0) {
			for (int j = 0; j < att.getLength(); j++) {
				entry.addAttribete(att.item(j).getNodeName(), att.item(j)
						.getNodeValue());
			}
		}

		NodeList nl = le.getChildNodes();
		// System.out.println(nl.getLength());
		if (nl.getLength() == 0)
			return entry;
		for (int i = 0; i < nl.getLength(); i++) {
			Node n = nl.item(i);
			if (n instanceof Element) {
				Element e = (Element) n;
				entry.addEntry(handle(e, entry));
			}
		}
		return entry;
	}

}
